﻿// Inner Fire 游戏引擎库
// AnimationClip - 动画片断
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 所属层级：应用层(4)
// 用于保存一个单独动画序列
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-03-14

#pragma once

#include "animation_channel.h"
#include <DirectXMath.h>
#include <EASTL/unordered_map.h>
#include <assimp/scene.h>
#include <game/animation/animation_def.h>
#include <graphics/graphics_def.h>
#include <memory>
#include <static_string.h>
#include <xml_reader.h>

namespace ifire::game {
class Animation;
class Avatar;

// Clip中的配置事件
struct AnimationEvent {
  // 事件的Index，因为有时候名称相同，所以需要Index来区别
  int index;
  // 项目的事件名称
  ikit::sstr name;
  // 所属的Clip名称，如果为空，表示从属于MasterClip
  ikit::sstr clip;
  // 事件触发的时间
  float time;

  AnimationEvent(const ikit::XmlNode& node, int index);
};

class AnimationClip {
public:
  // 通过默认初始化
  AnimationClip(Animation* parent, ikit::sstr _name);
  // 通过Node初始化
  AnimationClip(Animation* parent, const ikit::XmlNode& node);

  AnimationClip(const AnimationClip& lhs) = delete;
  AnimationClip& operator=(const AnimationClip& lhs) = delete;
  ~AnimationClip();

  // 读取一个Anime
  void Read(const aiAnimation* anim);
  // 表示是否是主CLIP，主CLIP中拥有从文件中读取的数据
  bool IsMaster() const { return is_master_; }
  // 从一个Master配置信息
  void SetMaster(AnimationClip* master_clip);

  // 根据当前的帧数，计算出目标Channel所对应的矩阵
  IMat CalcTransform(float frame, const AnimationChannel* channel) const;

  // 通过时间计算出帧数
  // 注意，这个帧数并不包括剪取项目的位移。比如从30-60范围的，是视为0-30。
  // 以后应该把这个统一，不应该在两地之间进行不同的协同，但目前暂时这样。
  float CalcFrame(float time_in_seconds, PlayMethod method) const;

  const AnimationChannel* FindChannel(ikit::sstr name);
  const AnimationChannel* FindChannelAvatar(ikit::sstr name, Avatar* chara);
  void Print();
  float GetStart() const { return start_frame_; }
  float GetEnd() const { return end_frame_; }
  float GetFrameCount() const { return frame_count_; }
  float GetDuration() const { return duration_; }
  float GetFps() const { return frame_per_second_; }
  bool HasEvent() const { return events.size() > 0; }
  Animation* GetAnimation() { return animation_; }
  const Avatar* GetAvatar() const;
  bool IsRootMotion() const;
  bool IsHumanoid() const;
  bool IsFlipRotation() const;
  FMat GetFlipRotation() const;
  IAxis GetRootMotionAxis() const;
  // 使这个项目载入
  void Ready();

public:
  // 项目的名称
  ikit::sstr name;
  // 需要引用的项目
  ikit::sstr master_name;
  // 项目的事件
  eastl::vector<AnimationEvent> events;

private:
  // 标记是否是Master项目，Master项目存放有读取的数据
  bool is_master_;

  // 此Clip所属的Animation（包括一些Avatar等信息，所以需要）
  Animation* animation_;
  // 此项目所引用的动画
  AnimationClip* master_clip_;
  // 每秒能够播放的帧数
  float frame_per_second_;
  // 此项目的持续时间，以帧数为单位。有些动画frame_per_second_=1，这个帧数就是小数。有些是整数。
  float frame_count_;
  // 此项目的持续时间，以秒为单位
  float duration_;
  // 开始的Frame，
  float start_frame_;
  // 结束的Frame
  float end_frame_;
  // 此动画的Key列表
  eastl::unordered_map<size_t, AnimationChannel*> channels_map_;
};

using AnimationClipPtr = std::unique_ptr<AnimationClip>;

} // namespace ifire::game